import fcntl
import time
+import signal
from threading import Thread
from xen.web.httpserver import HttpServer, UnixHttpServer
from SrvRoot import SrvRoot
from XMLRPCServer import XMLRPCServer
-
xroot = XendRoot.instance()
def add(self, server):
self.servers.append(server)
+ def cleanup(self, signum = 0, frame = None):
+ log.debug("SrvServer.cleanup()")
+ for server in self.servers:
+ try:
+ server.shutdown()
+ except:
+ pass
+
def start(self, status):
# Running the network script will spawn another process, which takes
# the status fd with it unless we set FD_CLOEXEC. Failing to do this
status.write('0')
status.close()
- for t in threads:
- t.join()
+ # Prepare to catch SIGTERM (received when 'xend stop' is executed)
+ # and call each server's cleanup if possible
+ signal.signal(signal.SIGTERM, self.cleanup)
+
+ # Interruptible Thread.join - Python Bug #1167930
+ # Replaces: for t in threads: t.join()
+ # Reason: The above will cause python signal handlers to be
+ # blocked so we're not able to catch SIGTERM in any
+ # way for cleanup
+ runningThreads = len([t for t in threads if t.isAlive()])
+ while runningThreads > 0:
+ try:
+ for t in threads:
+ t.join(1.0)
+ runningThreads = len([t for t in threads if t.isAlive()])
+ except:
+ pass
+
def create():
root = SrvDir()
# Copyright (C) 2006 XenSource Ltd.
#============================================================================
+from types import ListType
import xmlrpclib
-
-from xen.xend import XendDomain, XendDomainInfo, XendNode, \
- XendLogging, XendDmesg
from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer
-from xen.xend.XendClient import XML_RPC_SOCKET, ERROR_INVALID_DOMAIN
-from xen.xend.XendError import *
+from xen.xend import XendDomain, XendDomainInfo, XendNode
+from xen.xend import XendLogging, XendDmesg
+from xen.xend.XendClient import XML_RPC_SOCKET
from xen.xend.XendLogging import log
-from types import ListType
+from xen.xend.XendError import XendInvalidDomain
def lookup(domid):
info = XendDomain.instance().domain_lookup_by_name_or_id(domid)
finally:
f.close()
-methods = ['device_create', 'device_configure', 'destroyDevice',
- 'getDeviceSxprs',
+methods = ['device_create', 'device_configure',
+ 'destroyDevice','getDeviceSxprs',
'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
'send_sysrq', 'getVCPUInfo', 'waitForDevices',
'getRestartCount']
exclude = ['domain_create', 'domain_restore']
class XMLRPCServer:
- def __init__(self, use_tcp=False):
- self.ready = False
+ def __init__(self, use_tcp=False, host = "localhost", port = 8006,
+ path = XML_RPC_SOCKET):
self.use_tcp = use_tcp
+ self.port = port
+ self.host = host
+ self.path = path
+
+ self.ready = False
+ self.running = True
def run(self):
if self.use_tcp:
- # bind to something fixed for now as we may eliminate
- # tcp support completely.
- self.server = TCPXMLRPCServer(("localhost", 8005), logRequests=False)
+ self.server = TCPXMLRPCServer((self.host, self.port),
+ logRequests = False)
else:
- self.server = UnixXMLRPCServer(XML_RPC_SOCKET, False)
+ self.server = UnixXMLRPCServer(self.path, logRequests = False)
+
+ # Legacy deprecated xm xmlrpc api
+ # --------------------------------------------------------------------
# Functions in XendDomainInfo
for name in methods:
fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
self.server.register_function(fn, "xend.domain.%s" % name)
- # Functions in XendDomain
inst = XendDomain.instance()
+
for name in dir(inst):
fn = getattr(inst, name)
if name.startswith("domain_") and callable(fn):
self.server.register_introspection_functions()
self.ready = True
- self.server.serve_forever()
+
+ # Custom runloop so we can cleanup when exiting.
+ # -----------------------------------------------------------------
+ try:
+ self.server.socket.settimeout(1.0)
+ while self.running:
+ self.server.handle_request()
+ finally:
+ self.cleanup()
+
+ def cleanup(self):
+ log.debug("XMLRPCServer.cleanup()")
+
+ def shutdown(self):
+ self.running = False
+ self.ready = False
+